#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
void cleanup(void *arg){
    printf("clean up %s\n", (char *)arg);
}

void *thr_fn1(void *arg){
    printf("thread 1 start\n");
    pthread_cleanup_push(cleanup, "thread 1 first handler");
    pthread_cleanup_push(cleanup, "thread 1 second handler");
    printf("thread 1 push complete\n");

    if(arg){
        pthread_exit((void *)1);
    }
    pthread_cleanup_pop(0);
    pthread_cleanup_pop(0);
    pthread_exit((void *)1);
}

void *thr_fn2(void *arg){
    printf("thread 2 start\n");
    pthread_cleanup_push(cleanup, "thread 2 first handler");
    pthread_cleanup_push(cleanup, "thread 2 second handler");
    printf("thread 2 push complete\n");

    if(arg){
        return (void *)2;
    }
    pthread_cleanup_pop(0);
    pthread_cleanup_pop(0);
    return (void *)2;
}

int main(){
    pthread_t tid1, tid2;
    int err;
    void *tret;
    err = pthread_create(&tid1, NULL, thr_fn1, (void *)1);
    if(err){
        printf("pthread_create 1 error\n");
        exit(0);
    }
    err = pthread_create(&tid2, NULL, thr_fn2, (void *)1);
    if(err){
        printf("pthread_create 2 error\n");
        exit(0);
    }
    err = pthread_join(tid1, &tret);
    if(err){
        printf("pthread_join 1 error\n");
        exit(0);
    }
    printf("thread 1 exit code: %lu\n", (unsigned long)tret);
    err = pthread_join(tid2, &tret);
    if(err){
        printf("pthread_join 2 error\n");
        exit(0);
    }
    printf("thread 2 exit code: %lu\n", (unsigned long)tret);
    
    return 0;
}